#include "tcpmgr.h"
#include"usermgr.h"
#include"globalsignal.h"
#include"save.h"

#include <QTimer>

TcpMgr::~TcpMgr()
{
    qDebug("TcpMgr::~TcpMgr");
    _socket.close();
}

void TcpMgr::Close()
{
    _isReconnection = false;
    _socket.close();
}

TcpMgr::TcpMgr() {
    initHandlers();

    // 连接状态信号
    connect(&_socket, &QWebSocket::connected, this, [this] {
        qDebug() << "WebSocket connected!";
        emit sig_con_success(true);
    });

    // 接收二进制消息
    connect(&_socket, &QWebSocket::binaryMessageReceived, this, &TcpMgr::slot_ready_read);

    // 错误处理
    connect(&_socket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::errorOccurred), this, [this](QAbstractSocket::SocketError error) {
        qDebug() << "WebSocket error:" << _socket.errorString();
        emit sig_con_success(false);
    });

    // 断开连接处理
    connect(&_socket, &QWebSocket::disconnected, this, &TcpMgr::slot_disconnected);

    // 发送数据信号
    connect(this, &TcpMgr::sig_send_data, this, &TcpMgr::slot_send_data);
}

void TcpMgr::handleMsg(const ReqId id, const QByteArray& data) const
{
    auto find_iter =  _handlers.find(id);
    if(find_iter == _handlers.end()){
        qDebug()<< "not found id ["<< static_cast<int>(id) << "] to handle";
        return ;
    }

    QJsonParseError jsonError;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);

    if (jsonError.error != QJsonParseError::NoError){
        qDebug() << "JSON解析错误：" << jsonError.errorString();
        return;
    }
    QJsonObject jsonObj = jsonDoc.object();

    find_iter->second(jsonObj);
}

bool TcpMgr::isConnected() const
{
    return (_socket.state() == QAbstractSocket::ConnectedState);
}

void TcpMgr::slot_tcp_onnect(const ServerInfo& si)
{
    _host = si.Host;
    _port = si.Port.toUInt();
    qDebug() << si.Port;

    // 构造 WebSocket URL（假设使用非加密 ws://）
    QUrl url;
    url.setScheme("ws");
    url.setHost(_host);
    url.setPort(_port);
    qDebug() << url;

    // 创建 QNetworkRequest 并设置请求头
    QNetworkRequest request(url);
    // 获取 Uid 并转换为 QByteArray
    QByteArray uidArray = QString::number(UserMgr::GetInstance()->getUid()).toUtf8();
    request.setRawHeader("Uid", uidArray); // 设置认证头

    // 打开 WebSocket 连接时传入 request
    _socket.open(request); // 关键改动：使用 QNetworkRequest 而非直接 QUrl
}

void TcpMgr::slot_send_data(ReqId reqId, QByteArray  data)
{
    QJsonObject jsonO;
    jsonO["reqId"] = static_cast<int>(reqId);
    // 解析回 JSON 对象
    QJsonDocument parsedDoc = QJsonDocument::fromJson(data);
    if (!parsedDoc.isObject()) {
        return;
    };
    jsonO["data"] = parsedDoc.object();

    // 将 JSON 对象转换为字符串
    QJsonDocument doc(jsonO);
    QString jsonString = QString::fromUtf8(doc.toJson(QJsonDocument::Compact));

    // 发送二进制消息
    if (_socket.state() == QAbstractSocket::ConnectedState) {
        _socket.sendTextMessage(jsonString);
    } else {
        qDebug() << "未连接，无法发送消息";
    }
}

void TcpMgr::slot_ready_read(const QByteArray &message)
{
    qDebug() << "接受到数据！！！！";
    // 解析回 JSON 对象
    QJsonDocument parsedDoc = QJsonDocument::fromJson(message);
    if (!parsedDoc.isObject()) {
        return;
    };
    QJsonObject jsonO = parsedDoc.object();
    qDebug() << jsonO;
    ReqId id = static_cast<ReqId>(jsonO["reqId"].toInt());

    auto find_iter =  _handlers.find(id);
    if(find_iter == _handlers.end()){
        qDebug()<< "not found id ["<< static_cast<int>(id) << "] to handle";
        return ;
    }

    find_iter->second(jsonO);
}

void TcpMgr::slot_disconnected()
{
    if (!_isReconnection) return;

    QTimer *timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, [this, timer] {
        qDebug("尝试重连 WebSocket");
        if (!_isReconnection) {
            timer->stop();
            return;
        }

        _socket.open(QUrl(QString("ws://%1:%2").arg(_host).arg(_port)));
        if (_socket.state() == QAbstractSocket::ConnectedState) {
            timer->stop();
            qDebug("重连成功");

            // 发送重连后的认证请求
            QJsonObject jsonObj;
            jsonObj["token"] = UserMgr::GetInstance()->getToken();
            QJsonDocument doc(jsonObj);
            emit sig_send_data(ReqId::ID_CHAT_LOGIN, doc.toJson());
        }
    });
    timer->start(3000);
}

void TcpMgr::initHandlers()
{
    _handlers.insert(std::make_pair(ReqId::ID_CHAT_LOGIN, [this](const QJsonObject& jsonObj){
        int err = jsonObj["error"].toInt();
        if(err != 0){
            qDebug() << "Login Failed, err is " << err ;
            emit sig_login_failed(false);
            return;
        }

        UserMgr::GetInstance()->SetUid(jsonObj["uid"].toInt());
        UserMgr::GetInstance()->SetName(jsonObj["name"].toString());
        UserMgr::GetInstance()->SetToken(jsonObj["token"].toString());
        emit sig_login_failed(true);
    }));
    _handlers.insert(std::make_pair(ReqId::ID_SEARCH_USER_REQ, [this](const QJsonObject& jsonObj){
        int error = jsonObj["error"].toInt();
        if (static_cast<ErrorCodes>(error) != ErrorCodes::SUCCESS){
            emit sig_search_user(0);
            return;
        }
        emit sig_search_user(jsonObj["uid"].toInt());
    }));
    _handlers.insert(std::make_pair(ReqId::ID_ADD_FRIEND_REQ, [this](const QJsonObject& jsonObj){
        int error = jsonObj["error"].toInt();
        if (static_cast<ErrorCodes>(error) != ErrorCodes::SUCCESS){
            return;
        }
        QString name{jsonObj["name"].toString()};
        isGetAvatar(name);
        emit sig_add_friend_req(name, jsonObj["message"].toString());
    }));
    _handlers.insert(std::make_pair(ReqId::ID_AUTH_FRIEND_REQ, [](const QJsonObject& jsonObj){
        int error = jsonObj["error"].toInt();
        if (static_cast<ErrorCodes>(error) != ErrorCodes::SUCCESS){
            return;
        }
        emit GlobalSignal::GetInstance()->sig_add_friend(jsonObj["user"].toString());
    }));
    _handlers.insert(std::make_pair(ReqId::ID_TEXT_CHAT_MSG, [this](const QJsonObject& jsonObj){
        int error = jsonObj["error"].toInt();
        if (static_cast<ErrorCodes>(error) != ErrorCodes::SUCCESS){
            return;
        }
        emit sig_add_text_msg(jsonObj["sender"].toString(), jsonObj["message"].toString());
        QDateTime dateTime = QDateTime::currentDateTime();
        Save::GetInstance()->Add(jsonObj["message_id"].toInt(), jsonObj["sender"].toString(), jsonObj["message"].toString(), "text", jsonObj["sender"].toString(), dateTime);
    }));
    _handlers.insert(std::make_pair(ReqId::ID_CHAT_MSG_RSP, [](const QJsonObject& jsonObj){
        int error = jsonObj["error"].toInt();
        if (static_cast<ErrorCodes>(error) != ErrorCodes::SUCCESS){
            return;
        }
        qDebug() << jsonObj["message_id"].toInt() << "消息：" << jsonObj["message"].toString();
        QDateTime dateTime = QDateTime::currentDateTime();
        Save::GetInstance()->Add(jsonObj["message_id"].toInt(), jsonObj["receiver"].toString(), jsonObj["message"].toString(), "text", UserMgr::GetInstance()->getName(), dateTime);
    }));
}
